package com.gitee.wsl.serialization.id

/**
 * 通过一个数字作为ID值的 [ID] 实现。主要有2个子抽象类型：
 *
 * - [SignedNumericID] 有符号数字
 * - [UnsignedNumericID] 无符号数字
 *
 * 并由此扩展为4个具体的 ID 类型，按照最大可表示的数值按顺序为：
 *
 * - [IntID] 32位有符号整型
 * - [UIntID] 32位无符号整型
 * - [LongID] 64位有符号整型
 * - [ULongID] 64位无符号整型
 *
 * 如果想要作为ID的数字已经超过64位无符号 ([ULongID]) 锁能表示的最大数字，
 * 那么建议使用其他类型来表示，例如字符串ID [StringID] 或 UUID ([UUID]，也可以算是一个128位数字的ID)
 *
 *
 * @see SignedNumericID
 * @see UnsignedNumericID
 * @see IntID
 * @see UIntID
 * @see LongID
 * @see ULongID
 */
public sealed class NumericalID : ID() {

    /**
     * 将数字值转化为 [Double]。类似于 [Number.toDouble]
     */
    public abstract fun toDouble(): Double

    /**
     * 将数字值转化为 [Float]。类似于 [Number.toFloat]
     */
    public abstract fun toFloat(): Float

    /**
     * 将数字值转化为 [Long]。类似于 [Number.toLong]
     */
    public abstract fun toLong(): Long

    /**
     * 将数字值转化为 [ULong]。
     */
    public open fun toULong(): ULong =
        toLong().toULong()

    /**
     * 将数字值转化为 [Int]。类似于 [Number.toInt]
     */
    public abstract fun toInt(): Int

    /**
     * 将数字值转化为 [UInt]。
     */
    public open fun toUInt(): UInt =
        toInt().toUInt()

    /**
     * 将数字值转化为 [Short]。类似于 [Number.toShort]
     */
    public abstract fun toShort(): Short

    /**
     * 将数字值转化为 [Byte]。类似于 [Number.toByte]
     */
    public abstract fun toByte(): Byte

    final override fun compareTo(other: ID): Int {
        return when (other) {
            is StringID -> 1
            is NumericalID -> compareNumber(other)
        }
    }

    protected abstract fun compareNumber(target: NumericalID): Int

    public companion object {
        internal const val INT_MAX_ON_UINT: UInt = 2147483647u // Int.MAX_VALUE.toUInt()
        internal const val INT_MAX_ON_ULONG: ULong = 2147483647u // Int.MAX_VALUE
        internal const val LONG_MAX_ON_ULONG: ULong = 9223372036854775807u // Long.MAX_VALUE.toULong()
    }
}